/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.business.account.core.domain.account;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import info.peigen.hotpot.business.account.facade.enums.AccountDirection;
import info.peigen.hotpot.business.account.facade.enums.AccountTransCode;
import info.peigen.hotpot.common.core.domain.DomainObject;
import info.peigen.hotpot.common.core.lang.money.Money;
import info.peigen.hotpot.common.core.result.ResultCode;
import info.peigen.hotpot.common.core.util.IdUtil;
import info.peigen.hotpot.common.service.base.exception.BusinessException;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
import lombok.experimental.SuperBuilder;

import java.util.Date;

/**
 * <b>(AccountLog)</b>
 * 账户流水记录
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/8/12
 */
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@Accessors(chain = true)
public class AccountLog extends DomainObject {
    /** accountLogId */
    @Builder.Default
    String accountLogId = IdUtil.id();
    /** transLogId */
    String transLogId;
    /** 交易系统订单号 */
    @NotEmpty
    String           tradeId;
    /** 交易代码 */
    @NotNull
    AccountTransCode transCode;
    /** 账户 */
    @NotNull
    Account          account;
    /** 账户期初余额 */
    Money balance;
    /** 交易金额-包含币种 */
    @NotNull
    Money            transAmount;
    /** 借贷方向 */
    @NotNull
    AccountDirection direction;
    /** 交易时间 */
    @NotNull
    Date             transTime;
    /** 清算时间-有别与交易时间,应是实际资金清算系统提供的交易完成时间,视为清算时间 */
    Date   settleTime;
    /** memo */
    String memo;

    public static AccountLog income(Account account, Money balance, Money transAmount, String transLogId, String tradeId, Date settleTime, String memo) {
        Assert.notNull(transAmount, () -> new BusinessException(ResultCode.FAILURE, "交易金额不得为null"));
        // TODO Peigen 充电业务的特殊情况，以后想想怎么怎么解决，加个交易类型什么的
        // Assert.isTrue(transAmount.greaterThan(Money.zero()), () -> new BusinessException(ResultCode.FAILURE, "交易金额不得小于零"));

        return AccountLog.builder()
                .accountLogId(IdUtil.id())
                .transLogId(transLogId)
                .tradeId(tradeId)
                .transCode(AccountTransCode.Income)
                .account(account)
                .transAmount(transAmount)
                .balance(balance)
                .direction(AccountDirection.Credit)
                .transTime(DateUtil.date())
                .settleTime(settleTime)
                .memo(memo)
                .build();
    }

    public static AccountLog paid(Account account, Money balance, Money transAmount, String transLogId, String tradeId, Date settleTime, String memo) {
        Assert.notNull(transAmount, () -> new BusinessException(ResultCode.FAILURE, "交易金额不得为null"));
        // TODO Peigen 充电业务的特殊情况，以后想想怎么怎么解决，加个交易类型什么的
        // Assert.isTrue(transAmount.greaterThan(Money.zero()), () -> new BusinessException(ResultCode.FAILURE, "交易金额不得小于等于零"));

        return AccountLog.builder()
                .accountLogId(IdUtil.id())
                .transLogId(transLogId)
                .tradeId(tradeId)
                .transCode(AccountTransCode.Paid)
                .account(account)
                .transAmount(transAmount)
                .balance(balance)
                .direction(AccountDirection.Debit)
                .transTime(DateUtil.date())
                .settleTime(settleTime)
                .memo(memo)
                .build();
    }

    public static AccountLog paidRefund(Account account, Money balance, Money transAmount, String transLogId, String tradeId, Date settleTime, String memo) {
        Assert.notNull(transAmount, () -> new BusinessException(ResultCode.FAILURE, "交易金额不得为null"));
        Assert.isTrue(transAmount.greaterThan(Money.zero()), () -> new BusinessException(ResultCode.FAILURE, "交易金额不得小于零"));

        return AccountLog.builder()
                .accountLogId(IdUtil.id())
                .transLogId(transLogId)
                .tradeId(tradeId)
                .transCode(AccountTransCode.PaidRefund)
                .account(account)
                .transAmount(transAmount)
                .balance(balance)
                .direction(AccountDirection.Credit)
                .transTime(DateUtil.date())
                .settleTime(settleTime)
                .memo(memo)
                .build();
    }

    public static AccountLog feePaid(Account account, Money balance, Money feeAmount, String transLogId, String tradeId, String memo) {
        if (feeAmount.equals(Money.zero())) {
            return null;
        }

        return AccountLog.builder()
                .accountLogId(IdUtil.id())
                .transLogId(transLogId)
                .tradeId(tradeId)
                .transCode(AccountTransCode.Fee)
                .account(account)
                .transAmount(feeAmount)
                .balance(balance)
                .direction(AccountDirection.Debit)
                .transTime(DateUtil.date())
                .settleTime(DateUtil.date())
                .memo(memo)
                .build();
    }

    public static AccountLog feeIncome(Account account, Money balance, Money feeAmount, String transLogId, String tradeId, String memo) {
        if (feeAmount.equals(Money.zero())) {
            return null;
        }

        return AccountLog.builder()
                .accountLogId(IdUtil.id())
                .transLogId(transLogId)
                .tradeId(tradeId)
                .transCode(AccountTransCode.Fee)
                .account(account)
                .transAmount(feeAmount)
                .balance(balance)
                .direction(AccountDirection.Credit)
                .transTime(DateUtil.date())
                .settleTime(DateUtil.date())
                .memo(memo)
                .build();
    }
}